#include "StdAfx.h"
#include "DotFont_impl.h"

#include "GlyphGen.h"
#include "ImageBlob.h"

namespace dotfont{

using Gdiplus::Bitmap;
using Gdiplus::Graphics;
using Gdiplus::Pen;

DotFont_impl::DotFont_impl(void)
{
}

DotFont_impl::~DotFont_impl(void)
{
	for (size_t i = 0; i < blocks.size(); ++i)
	{
		delete blocks.at(i);
	}
	blocks.clear();
}

bool DotFont_impl::generate( const wchar_t* CharSet, 
							const wchar_t* FontName, float FontSize, Style S, const PixelFormat& pf, 
							const Size& EntrySize, const PointF& EntryOffset,
							int nEntryRow, int nEntryColumn,
							DWORD FontColor, DWORD BgColor, bool Antialiase)
{
	errmsg.clear();

	fontName = FontName;
	fontSize = FontSize;
	style = S;
	pixelFormat = pf;
	entrySize = EntrySize;
	palette = NULL;

	GlyphGen* gg = GlyphGenFactory::create(fontName, fontSize, style);
	assert(gg);

	const wstring str(CharSet);

	size_t bpp = pixelFormat.size();

	Size bmpSize(entrySize.Width * nEntryRow, entrySize.Height * nEntryColumn); 
	size_t stride = bpp / 8 * bmpSize.Width;
	stride = (stride + 3) & ~3;			// aligned in dword
	bmpSize.Width = stride * 8 / bpp;

	size_t cbPiece = stride * bmpSize.Height;
	size_t nPiece = (str.length() + nEntryRow * nEntryColumn - 1) / (nEntryRow * nEntryColumn);

	wstring::const_iterator begin = str.begin();
	wstring::const_iterator end = str.end();
	for (size_t i = 0; i < nPiece; ++i)
	{
		Block* block = new Block(Range(*begin, *(end - 1)), EntrySize, bmpSize, bpp, Size(nEntryRow, nEntryColumn));
		blocks.push_back(block);
		BYTE* pMem = block->getRawData();

		if (end - begin > nEntryRow * nEntryColumn)
			end = begin + nEntryRow * nEntryColumn;
		else
			end = str.end();

		gg->gen(begin, end, nEntryRow, nEntryColumn, entrySize, EntryOffset, 
			pMem, stride, bmpSize, pixelFormat,
			FontColor, BgColor, palette, Antialiase);

		begin = end;
		end = str.end();
	}

	delete gg;

	return true;
}

void DotFont_impl::dump( bool ShowGrid, const wchar_t* Prefix, const wchar_t* Path )
{
	size_t bpp = pixelFormat.size();
	
	wstring path;
	if (Path)
	{
		path = Path;
	}

	CLSID clsid;
	ImageBlob::getEncoderClsid(ImageBlob::tPNG, &clsid);

	if (path.length())
	{
		int r = _wmkdir(path.c_str());
		if (r != 0 && r != EEXIST)
		{
			errmsg = L"Dump failed: Specifying path isn't accessible.";
			return;
		}
		path += L"\\";
	}

	for (size_t i = 0; i < blocks.size(); ++i)
	{
		Block& block(*blocks[i]);
		Bitmap bmp(entrySize.Width * block.getBmpSizeInEntry().Width, 
			entrySize.Height * block.getBmpSizeInEntry().Height, 
			block.getBmpSize().Width * bpp / 8, pixelFormat, blocks[i]->getRawData());

		if (ShowGrid)
		{
			Graphics g(&bmp);
			Pen pen(Color::White);
			for (int p = 0; p < block.getBmpSizeInEntry().Width; ++p)
			{
				g.DrawLine(&pen, 
					p * entrySize.Width, 0,
					p * entrySize.Width,
					block.getBmpSize().Height);
			}
			for (int q = 0; q < block.getBmpSizeInEntry().Height; ++q)
			{
				g.DrawLine(&pen, 
					0, q * entrySize.Height,  
					block.getBmpSize().Width,
					q * entrySize.Height);
			}
		}

		wstringstream filename;
		filename << path << Prefix << i << L".png";

		bmp.Save(filename.str().c_str(), &clsid);
	}
}

bool DotFont_impl::generateWithStroke( const wchar_t* CharSet, const wchar_t* FontName, float FontSize, Style S, const PixelFormat& pf, const Size& EntrySize, DWORD StrokeColor, const PointF& EntryOffset, int nEntryRow, int nEntryColumn, DWORD FontColor, DWORD BgColor, bool Antialiase )
{
	errmsg.clear();

	fontName = FontName;
	fontSize = FontSize;
	style = S;
	pixelFormat = pf;
	entrySize = EntrySize;
	palette = NULL;

	GlyphGen* gg = GlyphGenFactory::create(fontName, fontSize, style, StrokeColor);
	assert(gg);

	const wstring str(CharSet);

	size_t bpp = pixelFormat.size();

	Size bmpSize(entrySize.Width * nEntryRow, entrySize.Height * nEntryColumn); 
	size_t stride = bpp / 8 * bmpSize.Width;
	stride = (stride + 3) & ~3;			// aligned in dword
	bmpSize.Width = stride * 8 / bpp;

	size_t cbPiece = stride * bmpSize.Height;
	size_t nPiece = (str.length() + nEntryRow * nEntryColumn - 1) / (nEntryRow * nEntryColumn);

	wstring::const_iterator begin = str.begin();
	wstring::const_iterator end = str.end();
	for (size_t i = 0; i < nPiece; ++i)
	{
		Block* block = new Block(Range(*begin, *(end - 1)), EntrySize, bmpSize, bpp, Size(nEntryRow, nEntryColumn));
		blocks.push_back(block);
		BYTE* pMem = block->getRawData();

		if (end - begin > nEntryRow * nEntryColumn)
			end = begin + nEntryRow * nEntryColumn;
		else
			end = str.end();

		gg->gen(begin, end, nEntryRow, nEntryColumn, entrySize, EntryOffset, 
			pMem, stride, bmpSize, pixelFormat,
			FontColor, BgColor, palette, Antialiase);

		begin = end;
		end = str.end();
	}

	delete gg;

	return true;
}

} // namespace dotfont
